package gui;

import engine.Cell;
import engine.Creature;
import engine.World;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * This class creates simple GUI for testing.
 */
public class TextGUI extends JPanel {
    public  TextGUI me = this;
    private World currentWorld;
    private JButton newCreature;
    private JButton nextDay;
    private JButton newCreatureInCell;
    private JButton setGrassButton;

    private JMenuBar menuBar;

    private JLabel numberLabel;

    private JPanel mainPanel;
    private JPanel secondPanel;
    private JPanel worldPanel;
    private JPanel cellPanel;
    private JPanel cellGrassPanel;
    private JPanel creaturePanel;
    private JPanel creaturePropertiesPanel;
    private JPanel creatureStatePanel;
    private JPanel creaturePhenotypePanel;
    private JPanel creatureGenotypePanel;
    private JPanel creatureColorPanel;
    private JPanel cellColorPanel;


    private JLabel yearLabel;
    private JLabel dayLabel;
    private JLabel cellNumberLabel;
    private JLabel cellGrassLabel;
    private JLabel cellFutureGrassLabel;
    private JLabel cellPreviousGrassLabel;
    private JTextField cellGrassField;
    private JLabel cellPopulation;
    private JLabel creatureNumberLabel;
    private JLabel creatureCellLabel;
    private JLabel creatureAgeLabel;
    private JLabel creatureTestosteroneLabel;
    private JLabel creatureWidthLabel;
    private JLabel creatureSpeedLabel;
    private JLabel creatureStaminaLabel;
    private JLabel creatureSexLabel;
    private JLabel creatureFoodNeedLabel;
    private JLabel creatureMeatPreferLabel;
    private JLabel creatureVisionLabel;
    private JLabel creatureHungerLabel;
    private JLabel creatureDecisionLabel;
    private JLabel creatureEnergyLabel;
    private JLabel creatureEnergyRecoveryLabel;
    private JLabel creatureMaxEnergyLabel;
    private JLabel creatureGenWidthLabel;
    private JLabel creatureGenSpeedLabel;
    private JLabel creatureGenStaminaLabel;
    private JLabel creatureGenFoodNeedLabel;
    private JLabel creatureFatherLabel;
    private JLabel creatureMotherLabel;
    private JLabel creatureAttackLabel;
    private JLabel creatureArmorLabel;
    private JLabel creatureHealthLabel;

    private JList<Cell> cellList;
    private JList<Creature> creatureList;
    public Cell currentCell;
    public Creature currentCreature;

    private JScrollPane scroll01;
    private JScrollPane logScroll;

    public JTextArea logArea;

    public DefaultListModel<Creature> creatureListModel;

    public void startGUI(World world) {
        currentWorld = world;
        JFrame frame = new JFrame();
        mainPanel = new JPanel();
        secondPanel = new JPanel();
        worldPanel = new JPanel();
        worldPanel.setBorder(new TitledBorder("World"));
        cellPanel = new JPanel();
        cellGrassPanel = new JPanel();
        cellPanel.setBorder(new TitledBorder("Cell"));
        creaturePhenotypePanel = new JPanel();
        creaturePhenotypePanel.setBorder(new TitledBorder("Phenotype"));
        creatureGenotypePanel = new JPanel();
        creatureGenotypePanel.setBorder(new TitledBorder("Genotype"));
        creatureStatePanel = new JPanel();
        creatureStatePanel.setBorder(new TitledBorder("Current state"));
        creaturePropertiesPanel = new JPanel();
        creaturePropertiesPanel.setBorder(new TitledBorder("Properties"));
        creaturePanel = new JPanel();
        creaturePanel.setBorder(new TitledBorder("Creature"));
        menuBar = new JMenuBar();

        JMenu newMenu = new JMenu("New");
        menuBar.add(newMenu);

        JMenuItem newCreatureItem = new JMenuItem("New creature");
        newCreatureItem.addActionListener(new NewCreatureActionListener());
        newMenu.add(newCreatureItem);

        JMenu timeMenu = new JMenu("Time");
        menuBar.add(timeMenu);

        JMenuItem dayItem = new JMenuItem("Next day");
        dayItem.addActionListener(new NextDayActionListener());
        timeMenu.add(dayItem);

        JMenuItem yearItem = new JMenuItem("Next year");
        yearItem.addActionListener(new NextYearActionListener());
        timeMenu.add(yearItem);


        frame.setJMenuBar(menuBar);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(BorderLayout.CENTER, mainPanel);

        mainPanel.setLayout(new GridLayout(1, 2));
        secondPanel.setLayout(new GridLayout(1, 2));
        mainPanel.add(secondPanel);
        secondPanel.add(worldPanel);
        secondPanel.add(cellPanel);
        mainPanel.add(creaturePanel);

        worldPanel.setLayout(new BoxLayout(worldPanel, BoxLayout.Y_AXIS));
        cellPanel.setLayout(new BoxLayout(cellPanel, BoxLayout.Y_AXIS));
        cellGrassPanel.setLayout(new BoxLayout(cellGrassPanel, BoxLayout.X_AXIS));
        creaturePanel.setLayout(new BoxLayout(creaturePanel, BoxLayout.Y_AXIS));
        creaturePropertiesPanel.setLayout(new BoxLayout(creaturePropertiesPanel, BoxLayout.X_AXIS));
        creatureStatePanel.setLayout(new BoxLayout(creatureStatePanel, BoxLayout.Y_AXIS));
        creaturePhenotypePanel.setLayout(new BoxLayout(creaturePhenotypePanel, BoxLayout.Y_AXIS));
        creatureGenotypePanel.setLayout(new BoxLayout(creatureGenotypePanel, BoxLayout.Y_AXIS));


        Font small = new Font("a", Font.CENTER_BASELINE, 10);

        // World panel
        yearLabel = new JLabel("Year № "+ currentWorld.getYearNumber());
        dayLabel = new JLabel("Day № "+ currentWorld.getDayNumber());
        numberLabel = new JLabel("Number of creatures: " + world.creaturesOfWorld.size());
        cellList = new JList<>(currentWorld.field);
        logArea = new JTextArea(world.shLog.toString());
        logScroll = new JScrollPane(logArea);
        logScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

        scroll01 = new JScrollPane(cellList);
        scroll01.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scroll01.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scroll01.setMinimumSize(new Dimension(120, 120));
        cellList.setVisibleRowCount(4);
        cellList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        cellList.addListSelectionListener(new CellSelectionActionListener());
        nextDay = new JButton("Next Day");
        nextDay.addActionListener(new NextDayActionListener());

        worldPanel.setBackground(Color.YELLOW);
        cellPanel.setBackground(Color.RED);
        creaturePanel.setBackground(Color.GRAY);
        worldPanel.add(yearLabel);
        worldPanel.add(dayLabel);
        worldPanel.add(nextDay);
        worldPanel.add(numberLabel);
        worldPanel.add(scroll01);
        worldPanel.add(logScroll);


        // Cell panel
        newCreatureInCell = new JButton("Create new creature");
        newCreatureInCell.setVisible(false);
        cellNumberLabel = new JLabel("Cell isn't selected");
        cellPreviousGrassLabel = new JLabel(" ");
        cellGrassLabel = new JLabel("   Future grass: ");
        cellGrassField = new JTextField(" ");
        cellFutureGrassLabel = new JLabel(" ");
        cellGrassField.setMaximumSize(new Dimension(100, 100));
        setGrassButton = new JButton("Set");
        setGrassButton.addActionListener( new setGrassActionListener());
        cellColorPanel = new JPanel();
        creatureListModel = new DefaultListModel<>();
        creatureList = new JList<>(creatureListModel);
        JScrollPane scroll02 = new JScrollPane(creatureList);
        scroll02.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scroll02.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scroll02.setMinimumSize(new Dimension(100, 300));
        cellColorPanel.setMaximumSize(new Dimension(3000, 3000));
        creatureList.setVisibleRowCount(4);
        creatureList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        creatureList.addListSelectionListener(new CreatureSelectionActionListener());

        cellPanel.add(newCreatureInCell);
        cellPanel.add(cellPreviousGrassLabel);
        cellPanel.add(cellFutureGrassLabel);
        cellPanel.add(cellGrassPanel);
        cellGrassPanel.add(cellGrassLabel);
        cellGrassPanel.add(cellGrassField);
        cellGrassPanel.add(setGrassButton);
        cellPanel.add(cellNumberLabel);
        cellPanel.add(cellColorPanel);
        cellPanel.add(scroll02);
        cellGrassPanel.setVisible(false);

        // Creature panel
        creatureNumberLabel = new JLabel("Creature isn't selected");
        creatureCellLabel = new JLabel(" ");
        creatureAgeLabel = new JLabel(" ");
        creatureTestosteroneLabel = new JLabel(" ");
        creatureSexLabel = new JLabel(" ");
        creatureWidthLabel = new JLabel(" ");
        creatureSpeedLabel = new JLabel(" ");
        creatureStaminaLabel = new JLabel(" ");
        creatureEnergyLabel = new JLabel(" ");
        creatureEnergyRecoveryLabel = new JLabel(" ");
        creatureMaxEnergyLabel = new JLabel(" ");
        creatureFoodNeedLabel = new JLabel(" ");
        creatureMeatPreferLabel = new JLabel(" ");
        creatureVisionLabel = new JLabel(" ");
        creatureHungerLabel = new JLabel(" ");
        creatureDecisionLabel = new JLabel(" ");
        creatureGenWidthLabel = new JLabel(" ");
        creatureGenSpeedLabel = new JLabel(" ");
        creatureGenStaminaLabel = new JLabel(" ");
        creatureGenFoodNeedLabel = new JLabel(" ");
        creatureFatherLabel = new JLabel(" ");
        creatureMotherLabel = new JLabel(" ");
        creatureAttackLabel = new JLabel(" ");
        creatureArmorLabel = new JLabel(" ");
        creatureHealthLabel = new JLabel(" ");

        creatureColorPanel = new JPanel();

        creaturePanel.add(creatureNumberLabel);
        creaturePanel.add(creatureCellLabel);
        creaturePanel.add(creatureAgeLabel);
        creaturePanel.add(creaturePropertiesPanel);

        creaturePropertiesPanel.add(creatureStatePanel);
        creaturePropertiesPanel.add(creaturePhenotypePanel);
        creaturePropertiesPanel.add(creatureGenotypePanel);

        creatureStatePanel.add(creatureHealthLabel);
        creatureStatePanel.add(creatureHungerLabel);
        creatureStatePanel.add(creatureEnergyLabel);
        creatureStatePanel.add(creatureTestosteroneLabel);
        creatureStatePanel.add(creatureDecisionLabel);

        creaturePhenotypePanel.add(creatureWidthLabel);
        creaturePhenotypePanel.add(creatureSpeedLabel);
        creaturePhenotypePanel.add(creatureStaminaLabel);
        creaturePhenotypePanel.add(creatureFoodNeedLabel);
        creaturePhenotypePanel.add(creatureMeatPreferLabel);
        creaturePhenotypePanel.add(creatureMaxEnergyLabel);
        creaturePhenotypePanel.add(creatureEnergyRecoveryLabel);
        creaturePhenotypePanel.add(creatureVisionLabel);
        creaturePhenotypePanel.add(creatureAttackLabel);
        creaturePhenotypePanel.add(creatureArmorLabel);

        creatureGenotypePanel.add(creatureFatherLabel);
        creatureGenotypePanel.add(creatureMotherLabel);
        creatureGenotypePanel.add(creatureSexLabel);
        creatureGenotypePanel.add(creatureGenWidthLabel);
        creatureGenotypePanel.add(creatureGenSpeedLabel);
        creatureGenotypePanel.add(creatureGenStaminaLabel);
        creatureGenotypePanel.add(creatureGenFoodNeedLabel);

        creatureGenotypePanel.add(creatureColorPanel);
        newCreatureInCell.setFont(small);
        newCreatureInCell.addActionListener(new NewCreatureInCellActionListener());

        frame.setSize(1500, 700);
        frame.setVisible(true);
    }

    public void drawWorldPanel() {
        yearLabel.setText("Year № " + currentWorld.getYearNumber());
        dayLabel.setText("Day № " + currentWorld.getDayNumber());
        numberLabel.setText("Number of creatures: " + currentWorld.creaturesOfWorld.size());
        scroll01.updateUI();
        logArea.append(currentWorld.shLog.toString());
        logArea.setCaretPosition(logArea.getDocument().getLength());
        currentWorld.shLog = new StringBuilder();
    }

    public void drawCellPanel() {
        if (currentCell == null) {
            cellNumberLabel.setText("Cell isn't selected");
        } else {
            cellNumberLabel.setText("Cell number " + currentCell.getXPosition() + "x" + currentCell.getYPosition());
            newCreatureInCell.setVisible(true);
            cellGrassPanel.setVisible(true);
            cellPreviousGrassLabel.setText("Grass: " + currentCell.getGrass());
            cellFutureGrassLabel.setText("Future grass: " + currentCell.getFutureGrass());
            creatureList.setListData(currentCell.creaturesOfCell.toArray(new Creature[0]));
            cellColorPanel.setBackground(currentCell.color);
        }

    }


    public void drawCreaturePanel() {
        if (currentCreature == null) {
            creatureNumberLabel.setText("Creature isn't selected");
            creatureCellLabel.setText("");
        } else {
            if (currentCreature.isAlive){
                creatureAgeLabel.setText("Creature age is " + currentCreature.getAge());
            }else {
                creatureAgeLabel.setText("Creature is dead");
            }
            creatureEnergyRecoveryLabel.setText("Energy recovery " + currentCreature.getEnergyRecovery());
            creatureMaxEnergyLabel.setText("Max energy " + currentCreature.getMaxEnergy());
            creatureTestosteroneLabel.setText("Testosterone " + currentCreature.getTestosterone());
            creatureNumberLabel.setText("Creature №" + currentCreature.number);
            creatureCellLabel.setText("Creature position " + currentCreature.position.getXPosition() + "x" + currentCreature.position.getYPosition());
            creatureSexLabel.setText("Creature is " + currentCreature.getSex());
            creatureWidthLabel.setText("Width is " + currentCreature.getWidth());
            creatureEnergyLabel.setText("Energy " + currentCreature.getEnergy());
            creatureVisionLabel.setText("Vision " + currentCreature.getVision());
            creatureGenWidthLabel.setText("Gen width is " + currentCreature.getGenWidth());
            creatureSpeedLabel.setText("Speed is " + currentCreature.getSpeed());
            creatureGenSpeedLabel.setText("Gen speed is " + currentCreature.getGenSpeed());
            creatureStaminaLabel.setText("Stamina is " + currentCreature.getStamina());
            creatureGenStaminaLabel.setText("Gen stamina is " + currentCreature.getGenStamina());
            creatureFoodNeedLabel.setText("Need of food is " + currentCreature.getFoodNeed());
            creatureMeatPreferLabel.setText("Meat prefer is " + currentCreature.getMeatPrefer());
            creatureGenFoodNeedLabel.setText("Gen need of food is " + currentCreature.getGenFoodNeed());
            creatureSexLabel.setText("Creature is " + currentCreature.getSex());
            creatureHungerLabel.setText("Hunger " + currentCreature.getHunger());
            creatureDecisionLabel.setText("Last decision " + currentCreature.decision);
            creatureFatherLabel.setText("Father " + currentCreature.getFather());
            creatureMotherLabel.setText("Mother " + currentCreature.getMother());
            creatureAttackLabel.setText("Attack " + currentCreature.getAttack());
            creatureArmorLabel.setText("Armor " + currentCreature.getArmor());
            creatureHealthLabel.setText("Health " + currentCreature.getHealth());
            creatureColorPanel.setBackground(currentCreature.getColor());
        }

    }

    private void createUIComponents() {
        // TODO: place custom component creation code here
    }


    class NewCreatureInCellActionListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            NewCreature.start(currentCell, me);
        }
    }

    class NewCreatureActionListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            NewCreature.start(currentWorld, me);
        }
    }

    class CellSelectionActionListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent event) {
            if (!event.getValueIsAdjusting()) {
                if (cellList.getSelectedValue() != null) {
                    currentCell = (Cell) cellList.getSelectedValue();
                    drawCellPanel();
                    drawWorldPanel();                }

            }

        }
    }

    class CreatureSelectionActionListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent event) {
            if (!event.getValueIsAdjusting()) {
                if (creatureList.getSelectedValue() != null) {
                    currentCreature = creatureList.getSelectedValue();
                }
                drawCreaturePanel();
            }

        }
    }

    class NextDayActionListener implements ActionListener{
        public void actionPerformed(ActionEvent event){
            currentWorld.worldDay();
            drawWorldPanel();
            drawCellPanel();
            drawCreaturePanel();
        }
    }

    class NextYearActionListener implements ActionListener{
        public void actionPerformed(ActionEvent event){
            for(int i = 0; i < currentWorld.DAYS_IN_YEAR; i++) {
                currentWorld.worldDay();
            }
            drawWorldPanel();
            drawCellPanel();
            drawCreaturePanel();
        }
    }

    private class setGrassActionListener implements ActionListener {
        public void actionPerformed(ActionEvent event){
            if (cellGrassField.getText().trim().matches("[0-9]+")) {
                currentCell.setFutureGrass(Integer.parseInt(cellGrassField.getText().trim()));
                drawCellPanel();
            }
        }
    }
}
